﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RaisingStudio.Data.Providers;
using RaisingStudio.Data.Providers.Adapters;
using System.Linq.Expressions;
using RaisingStudio.Data.Providers.Adapters.Generic;
#if NET_2_0
using RaisingStudio.Linq;
#endif

namespace RaisingStudio.Data.Linq
{
    public static class DataContextExtension
    {
        public static QueryableData<T> GetQueryableData<T>(this DataContext dataContext)
        {
            return new QueryableData<T>(dataContext);
        }


        public static ExpressionData<T, S> GetExpressionData<T, S>(this DataContext dataContext)
        {
            return new ExpressionData<T, S>(dataContext);
        }

        public static ExpressionData<T, S> GetExpressionData<T, S>(this DataContext dataContext, T value)
        {
            return new ExpressionData<T, S>(dataContext, value);
        }

        public static ExpressionData<T, S> GetExpressionData<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression<T> queryExpression)
        {
            return new ExpressionData<T, S>(dataContext, queryExpression.Value, queryExpression.Table, queryExpression.Condition, queryExpression.Columns);
        }


        #region Basic functions
        public static int GetCount<T>(this DataContext dataContext, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.GetDataCount(condition);
        }

        public static int GetCount<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return GetCount<T>(dataContext, conditionCommand);
        }

  
        public static RaisingStudio.Data.Expressions.ColumnExpression GetColumnExpression(Expression expression)
        {
            return CommandBuilder.GetColumnExpression(expression);
        }

        
        public static object GetSum<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.GetSumData((string)column, condition);
        }

        public static object GetSum<T>(this DataContext dataContext, Expression<Func<T, object>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return dataContext.GetSum<T>(columnExpression);
        }

        public static object GetSum<T>(this DataContext dataContext, Expression<Func<T, object>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return dataContext.GetSum<T>(columnExpression, conditionCommand);
        }

        public static S GetSum<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column)
        {
            object s = dataContext.GetSum<T>(column);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;                
            }
        }

        public static S GetSum<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, RaisingStudio.Data.Expressions.ConditionExpression condition)
        {
            object s = dataContext.GetSum<T>(column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetSum<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            object s = dataTableAdapter.GetSumData((string)column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetSum<T, S>(this DataContext dataContext, Expression<Func<T, S>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return GetSum<T, S>(dataContext, columnExpression);
        }

        public static S GetSum<T, S>(this DataContext dataContext, Expression<Func<T, S>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return GetSum<T, S>(dataContext, columnExpression, conditionCommand);
        }


        public static object GetAvg<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.GetAvgData((string)column, condition);
        }

        public static object GetAvg<T>(this DataContext dataContext, Expression<Func<T, object>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return dataContext.GetAvg<T>(columnExpression);
        }

        public static object GetAvg<T>(this DataContext dataContext, Expression<Func<T, object>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return dataContext.GetAvg<T>(columnExpression, conditionCommand);
        }

        public static S GetAvg<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column)
        {
            object s = dataContext.GetAvg<T>(column);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetAvg<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, RaisingStudio.Data.Expressions.ConditionExpression condition)
        {
            object s = dataContext.GetAvg<T>(column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetAvg<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            object s = dataTableAdapter.GetAvgData((string)column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetAvg<T, S>(this DataContext dataContext, Expression<Func<T, S>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return GetAvg<T, S>(dataContext, columnExpression);
        }

        public static S GetAvg<T, S>(this DataContext dataContext, Expression<Func<T, S>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return GetAvg<T, S>(dataContext, columnExpression, conditionCommand);
        }


        public static object GetMax<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.GetMaxData((string)column, condition);
        }

        public static object GetMax<T>(this DataContext dataContext, Expression<Func<T, object>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return dataContext.GetMax<T>(columnExpression);
        }

        public static object GetMax<T>(this DataContext dataContext, Expression<Func<T, object>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return dataContext.GetMax<T>(columnExpression, conditionCommand);
        }
        
        public static S GetMax<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column)
        {
            object s = dataContext.GetMax<T>(column);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMax<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, RaisingStudio.Data.Expressions.ConditionExpression condition)
        {
            object s = dataContext.GetMax<T>(column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {                
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMax<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            object s = dataTableAdapter.GetMaxData((string)column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMax<T, S>(this DataContext dataContext, Expression<Func<T, S>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return GetMax<T, S>(dataContext, columnExpression);
        }

        public static S GetMax<T, S>(this DataContext dataContext, Expression<Func<T, S>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return GetMax<T, S>(dataContext, columnExpression, conditionCommand);
        }


        public static object GetMin<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.GetMinData((string)column, condition);
        }

        public static object GetMin<T>(this DataContext dataContext, Expression<Func<T, object>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return dataContext.GetMin<T>(columnExpression);
        }

        public static object GetMin<T>(this DataContext dataContext, Expression<Func<T, object>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return dataContext.GetMin<T>(columnExpression, conditionCommand);
        }

        public static S GetMin<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column)
        {
            object s = dataContext.GetMin<T>(column);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMin<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, RaisingStudio.Data.Expressions.ConditionExpression condition)
        {
            object s = dataContext.GetMin<T>(column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMin<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.ColumnExpression column, CommonCommand condition)
        {
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            object s = dataTableAdapter.GetMinData((string)column, condition);
            if (s is DBNull)
            {
                return default(S);
            }
            else
            {
#if (PocketPC || Smartphone || WindowsCE)
                            s = Convert.ChangeType(s, typeof(S), null);
#else
                s = Convert.ChangeType(s, typeof(S));
#endif
                return (S)s;
            }
        }

        public static S GetMin<T, S>(this DataContext dataContext, Expression<Func<T, S>> column)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            return GetMin<T, S>(dataContext, columnExpression);
        }

        public static S GetMin<T, S>(this DataContext dataContext, Expression<Func<T, S>> column, Expression<Func<T, bool>> condition)
        {
            RaisingStudio.Data.Expressions.ColumnExpression columnExpression = GetColumnExpression(column);
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return GetMin<T, S>(dataContext, columnExpression, conditionCommand);
        }
        #endregion

        public static RaisingStudio.Data.Expressions.ColumnExpression[] GetColumnExpressions(Expression expression)
        {
            return CommandBuilder.GetColumnExpressions(expression);
        }

        public static string[] GetColumnNames(RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            if (columns != null)
            {
                string[] columnNames = new string[columns.Length];
                for (int i = 0; i < columns.Length; i++)
                {
                    columnNames[i] = (string)columns[i];
                }
                return columnNames;
            }
            return null;
        }


        public static IEnumerable<T> Query<T>(this DataContext dataContext, CommonCommand condition, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columns == null) || (columns.Length == 0))
            {
                return dataObjectAdapter.GetEnumerator(condition);
            }
            else
            {
                return dataObjectAdapter.GetEnumerator(GetColumnNames(columns), condition);
            }
        }
        
        public static IEnumerable<T> Query<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return Query<T>(dataContext, conditionCommand, columnExpressions);
        }
    
        public static IEnumerable<T> Query<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return Query<T>(dataContext, conditionCommand);
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, CommonCommand condition, int startRecord, int maxRecords, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columns == null) || (columns.Length == 0))
            {
                return dataObjectAdapter.GetEnumerator(condition, startRecord, maxRecords);
            }
            else
            {
                return dataObjectAdapter.GetEnumerator(GetColumnNames(columns), condition, startRecord, maxRecords);
            }
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return Query<T>(dataContext, conditionCommand, startRecord, maxRecords, columnExpressions);
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return Query<T>(dataContext, conditionCommand, startRecord, maxRecords);
        }


        public static List<T> QueryForList<T>(this DataContext dataContext, CommonCommand condition, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columns == null) || (columns.Length == 0))
            {
                return dataObjectAdapter.GetDataList(condition);
            }
            else
            {
                return dataObjectAdapter.GetDataList(GetColumnNames(columns), condition);
            }
        }
        
        public static List<T> QueryForList<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return QueryForList<T>(dataContext, conditionCommand, columnExpressions);
        }
        
        public static List<T> QueryForList<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return QueryForList<T>(dataContext, conditionCommand);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, CommonCommand condition, int startRecord, int maxRecords, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columns == null) || (columns.Length == 0))
            {
                return dataObjectAdapter.GetDataList(condition, startRecord, maxRecords);
            }
            else
            {
                return dataObjectAdapter.GetDataList(GetColumnNames(columns), condition, startRecord, maxRecords);
            }
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return QueryForList<T>(dataContext, conditionCommand, startRecord, maxRecords, columnExpressions);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return QueryForList<T>(dataContext, conditionCommand, startRecord, maxRecords);
        }


        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, CommonCommand condition, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            if ((columns == null) || (columns.Length == 0))
            {
                return dataContext.Provider.GetDataTable(typeof(T), condition);
            }
            else
            {
                return dataContext.Provider.GetDataTable(typeof(T), GetColumnNames(columns), condition);
            }
        }
        
        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return QueryForDataTable<T>(dataContext, conditionCommand, columnExpressions);
        }
        
        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return QueryForDataTable<T>(dataContext, conditionCommand);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, CommonCommand condition, int startRecord, int maxRecords, params RaisingStudio.Data.Expressions.ColumnExpression[] columns)
        {
            if ((columns == null) || (columns.Length == 0))
            {
                return dataContext.Provider.GetDataTable(typeof(T), condition, startRecord, maxRecords);
            }
            else
            {
                return dataContext.Provider.GetDataTable(typeof(T), GetColumnNames(columns), condition, startRecord, maxRecords);
            }
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return QueryForDataTable<T>(dataContext, conditionCommand, startRecord, maxRecords, columnExpressions);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, int startRecord, int maxRecords)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            return QueryForDataTable<T>(dataContext, conditionCommand, startRecord, maxRecords);
        }


        #region Datatable
        public static int UpdateDataTable<T>(this DataContext dataContext, System.Data.DataTable dataTable, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return dataContext.Provider.Update(typeof(T), dataTable);
            }
            else
            {
                return dataContext.Provider.Update(typeof(T), dataTable, columnExpressions);
            }
        }

        public static System.Data.DataTable CreateDataTable<T>(this DataContext dataContext, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T)).CreateDataTable();
            }
            else
            {
                string[] columnNames = GetColumnNames(columnExpressions);
                return (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T)).CreateDataTable(columnNames);
            }
        }


        public static int FillDataTable<T>(this DataContext dataContext, System.Data.DataTable dataTable, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return (dataContext.Provider as DataProvider).Fill<T>(dataTable, conditionCommand);
            }
            else
            {
                return (dataContext.Provider as DataProvider).Fill<T>(dataTable, GetColumnNames(columnExpressions), conditionCommand);
            }
        }

        public static int FillDataTable<T>(this DataContext dataContext, System.Data.DataTable dataTable, Expression<Func<T, bool>> condition, int startRecord, int maxRecords, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return (dataContext.Provider as DataProvider).Fill<T>(dataTable, conditionCommand, startRecord, maxRecords);
            }
            else
            {
                return (dataContext.Provider as DataProvider).Fill<T>(dataTable, GetColumnNames(columnExpressions), conditionCommand, startRecord, maxRecords);
            }
        }
        #endregion

        #region  Single entity
        public static T QueryForSingle<T>(this DataContext dataContext, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.GetData<T>(dataObject, columnExpressions);
        }

        public static T QueryForSingle<T>(this DataContext dataContext, object primaryKey, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.GetData<T>(primaryKey, columnExpressions);
        }

        public static T QueryForSingle<T>(this DataContext dataContext, object[] primaryKeys, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.GetData<T>(primaryKeys, columnExpressions);
        }

        public static T QueryForSingle<T>(this DataContext dataContext, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            IList<T> list = QueryForList<T>(dataContext, condition, 0, 1, columns);
            if ((list != null) && (list.Count > 0))
            {
                return list[0];
            }
            return default(T);
        }

        public static T QueryForSingle<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            IList<T> list = QueryForList<T>(dataContext, condition, 0, 1);
            if ((list != null) && (list.Count > 0))
            {
                return list[0];
            }
            return default(T);
        }


        public static int Insert<T>(this DataContext dataContext, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Insert<T>(dataObject, columnExpressions);
        }


        public static int Update<T>(this DataContext dataContext, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Update<T>(dataObject, columnExpressions);
        }

        public static int Update<T>(this DataContext dataContext, object primaryKey, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Update<T>(primaryKey, dataObject, columnExpressions);
        }

        public static int Update<T>(this DataContext dataContext, object[] primaryKeys, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Update<T>(primaryKeys, dataObject, columnExpressions);
        }


        public static int Save<T>(this DataContext dataContext, T dataObject, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Save<T>(dataObject, columnExpressions);
        }
        #endregion

        #region Batch operation
        public static int DeleteByQuery<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.Delete(conditionCommand);
        }

        public static bool ExistsByQuery<T>(this DataContext dataContext, Expression<Func<T, bool>> condition)
        {
            return (GetCount<T>(dataContext, condition) > 0) ? true : false;
        }

        public static int UpdateByQuery<T>(this DataContext dataContext, T dataObject, Expression<Func<T, bool>> condition, Expression<Func<T, object>> columns)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(condition);
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, conditionCommand);
            }
            else
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, columnExpressions, conditionCommand);
            }
        }
        #endregion

        #region Bulk operation
        public static int Update<T>(this DataContext dataContext, IList<T> dataObjectList, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Update<T>(dataObjectList, columnExpressions);
        }

        public static int Insert<T>(this DataContext dataContext, IList<T> dataObjectList, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Insert<T>(dataObjectList, columnExpressions);
        }

        public static int Save<T>(this DataContext dataContext, IList<T> dataObjectList, Expression<Func<T, object>> columns)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions = GetColumnExpressions(columns);
            return dataContext.Save<T>(dataObjectList, columnExpressions);
        }
        #endregion


        #region IQueryable
        public static IEnumerable<T> Query<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return Query<T>(dataContext, command, columns);
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, IQueryable queryable, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return Query<T>(dataContext, command, startRecord, maxRecords, columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return QueryForList<T>(dataContext, command, columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, IQueryable queryable, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return QueryForList<T>(dataContext, command, startRecord, maxRecords, columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return QueryForDataTable<T>(dataContext, command, columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, IQueryable queryable, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            return QueryForDataTable<T>(dataContext, command, startRecord, maxRecords, columns);
        }

        #region Basic functions
        public static int GetCount<T>(this DataContext dataContext, IQueryable queryable)
        {
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression);
            return GetCount<T>(dataContext, command);
        }

        public static object GetSum<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetSum<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetAvg<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetAvg<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetMax<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMax<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetMin<T>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMin<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static S GetSum<T, S>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetSum<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetAvg<T, S>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetAvg<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetMax<T, S>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMax<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetMin<T, S>(this DataContext dataContext, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryable.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMin<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }
        #endregion

        public static T QueryForSingle<T>(this DataContext dataContext, IQueryable queryable)
        {
            var q = Query<T>(dataContext, queryable, 0, 1);
            if (q != null)
            {
                foreach (T t in q)
                {
                    return t;
                }
            }
            return default(T);
        }

        #region Batch operation
        public static int DeleteByQuery<T>(this DataContext dataContext, IQueryable queryable)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(queryable.Expression);
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.Delete(conditionCommand);
        }

        public static bool ExistsByQuery<T>(this DataContext dataContext, IQueryable queryable)
        {
            return (GetCount<T>(dataContext, queryable) > 0) ? true : false;
        }

        public static int UpdateByQuery<T>(this DataContext dataContext, T dataObject, IQueryable queryable)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions;
            CommonCommand conditionCommand = CommandBuilder.GetCommand(queryable.Expression, out columnExpressions);
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, conditionCommand);
            }
            else
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, columnExpressions, conditionCommand);
            }
        }
        #endregion
        #endregion

        #region IQueryableData
        public static IEnumerable<T> Query<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return Query<T>(dataContext, command, columns);
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, IQueryableData queryableData, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return Query<T>(dataContext, command, startRecord, maxRecords, columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return QueryForList<T>(dataContext, command, columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, IQueryableData queryableData, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return QueryForList<T>(dataContext, command, startRecord, maxRecords, columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return QueryForDataTable<T>(dataContext, command, columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, IQueryableData queryableData, int startRecord, int maxRecords)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            return QueryForDataTable<T>(dataContext, command, startRecord, maxRecords, columns);
        }
        
        #region Basic functions
        public static int GetCount<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression);
            return GetCount<T>(dataContext, command);
        }

        public static object GetSum<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetSum<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetAvg<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetAvg<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetMax<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMax<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static object GetMin<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMin<T>(dataContext, columns[0], command);
            }
            return null;
        }

        public static S GetSum<T, S>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetSum<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetAvg<T, S>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetAvg<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetMax<T, S>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMax<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }

        public static S GetMin<T, S>(this DataContext dataContext, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns;
            CommonCommand command = CommandBuilder.GetCommand(queryableData.Expression, out columns);
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMin<T, S>(dataContext, columns[0], command);
            }
            return default(S);
        }
        #endregion

        public static T QueryForSingle<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            var q = Query<T>(dataContext, queryableData, 0, 1);
            if (q != null)
            {
                foreach (T t in q)
                {
                    return t;
                }
            }
            return default(T);
        }

        #region Batch operation
        public static int DeleteByQuery<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            CommonCommand conditionCommand = CommandBuilder.GetCommand(queryableData.Expression);
            DataTableAdapter dataTableAdapter = (dataContext.Provider as DataProvider).GetDataTableAdapter(typeof(T));
            return dataTableAdapter.Delete(conditionCommand);
        }

        public static bool ExistsByQuery<T>(this DataContext dataContext, IQueryableData queryableData)
        {
            return (GetCount<T>(dataContext, queryableData) > 0) ? true : false;
        }

        public static int UpdateByQuery<T>(this DataContext dataContext, T dataObject, IQueryableData queryableData)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columnExpressions;
            CommonCommand conditionCommand = CommandBuilder.GetCommand(queryableData.Expression, out columnExpressions);
            DataObjectAdapter<T> dataObjectAdapter = (dataContext.Provider as DataProvider).GetDataObjectAdapter<T>();
            if ((columnExpressions == null) || (columnExpressions.Length == 0))
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, conditionCommand);
            }
            else
            {
                return dataObjectAdapter.UpdateByCondition(dataObject, columnExpressions, conditionCommand);
            }
        }
        #endregion
        #endregion

        #region IQueryExpression

        public static IEnumerable<T> Query<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.Query<T>(queryExpression.Condition, queryExpression.Columns);
        }

        public static IEnumerable<T> Query<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression, int startRecord, int maxRecords)
        {
            return dataContext.Query<T>(queryExpression.Condition, startRecord, maxRecords, queryExpression.Columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.QueryForList<T>(queryExpression.Condition, queryExpression.Columns);
        }

        public static List<T> QueryForList<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression, int startRecord, int maxRecords)
        {
            return dataContext.QueryForList<T>(queryExpression.Condition, startRecord, maxRecords, queryExpression.Columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.QueryForDataTable<T>(queryExpression.Condition, queryExpression.Columns);
        }

        public static System.Data.DataTable QueryForDataTable<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression, int startRecord, int maxRecords)
        {
            return dataContext.QueryForDataTable<T>(queryExpression.Condition, startRecord, maxRecords, queryExpression.Columns);
        }

        #region Basic functions
        public static int GetCount<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.GetCount<T>(queryExpression.Condition);
        }

        public static object GetSum<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return dataContext.GetSum<T>(columns[0], queryExpression.Condition);
            }
            return null;
        }

        public static object GetAvg<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return dataContext.GetAvg<T>(columns[0], queryExpression.Condition);
            }
            return null;
        }

        public static object GetMax<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return dataContext.GetMax<T>(columns[0], queryExpression.Condition);
            }
            return null;
        }

        public static object GetMin<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return dataContext.GetMin<T>(columns[0], queryExpression.Condition);
            }
            return null;
        }

        public static S GetSum<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return GetSum<T, S>(dataContext, columns[0], queryExpression.Condition);
            }
            return default(S);
        }

        public static S GetAvg<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return GetAvg<T, S>(dataContext, columns[0], queryExpression.Condition);
            }
            return default(S);
        }

        public static S GetMax<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMax<T, S>(dataContext, columns[0], queryExpression.Condition);
            }
            return default(S);
        }

        public static S GetMin<T, S>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            RaisingStudio.Data.Expressions.ColumnExpression[] columns = queryExpression.Columns;
            if ((columns != null) && (columns.Length > 0))
            {
                return GetMin<T, S>(dataContext, columns[0], queryExpression.Condition);
            }
            return default(S);
        }
        #endregion

        public static T QueryForSingle<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            var q = Query<T>(dataContext, queryExpression, 0, 1);
            if (q != null)
            {
                foreach (T t in q)
                {
                    return t;
                }
            }
            return default(T);
        }

        #region Batch operation
        public static int DeleteByQuery<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.Delete<T>(queryExpression.Condition);
        }

        public static bool ExistsByQuery<T>(this DataContext dataContext, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return (GetCount<T>(dataContext, queryExpression) > 0) ? true : false;
        }

        public static int UpdateByQuery<T>(this DataContext dataContext, T dataObject, RaisingStudio.Data.Expressions.IQueryExpression queryExpression)
        {
            return dataContext.Update<T>(dataObject, queryExpression.Condition, queryExpression.Columns);
        }
        #endregion
        #endregion
    }
}
